type Node     native;  // *vdom.Node
type Styles   native;  // *vdom.Styles
type Attrs    native;  // *vdom.Attrs
type Events   native;  // *vdom.Events
type Content  native;  // vdom.Content

type Tag String;
type EventHandler native;  // *vdom.EventHandler
type EventPayload native;  // *qt.WebUiEventPayload (contains a C++ pointer)

/// Be careful!
/// Following constructors create pointers so that they are NOT pure functions.

/// Be careful!
/// The vDOM driver in `bridge.js` uses the memory address of a vNode as an ID.
/// Therefore, a vNode cannot be used more than once.
/// In addition, due to some restrictions, a vNode cannot move across subtrees.


export function Node:
    &(Tag) => Node
    native '__UiVdomNode';

export function Node:
    &(Tag, String) => Node
    &(tag, text) =>
        { Node tag }
            . { with { Content text } };

export function Node:
    &(Tag, List[Node]) => Node
    &(tag, children) =>
        { Node tag }
            . { with { Content children } };


export function Styles:
    &(Map[String,String]) => Styles
    native '__UiVdomStyles';

export function Styles:
    &(List[(String,String)]) => Styles
    &(styles) => { Styles { Map styles } };

export function with:
    &(Node, Styles) => Node
    native '__UiVdomNodeWithStyles';


export function Attrs:
    &(Map[String,String]) => Attrs
    native '__UiVdomAttrs';

export function Attrs:
    &(List[(String,String)]) => Attrs
    &(attrs) => { Attrs { Map attrs } };

export function with:
    &(Node, Attrs) => Node
    native '__UiVdomNodeWithAttrs';


export function Events:
    &(Map[String,EventHandler]) => Events
    native '__UiVdomEvents';

export function Events:
    &(List[(String,EventHandler)]) => Events
    &(events) => { Events  { Map events } };

export function EventHandler:[T]
    &(Sink[T], &(EventPayload) => T) => Sync[EventHandler]
    native '__UiVdomEventHandler';
    // note: payload is deleted after the T value is sent to the sink

export function with:
    &(Node, Events) => Node
    native '__UiVdomNodeWithEvents';


export function Content:
    &(String) => Content
    native '__UiVdomText';

export function Content:
    &(List[Node]) => Content
    native '__UiVdomChildren';

export function with:
    &(Node, Content) => Node
    native '__UiVdomNodeWithContent';


export function get-bool:
    &(EventPayload, String) => Bool
    native '__UiEventPayloadGetBool';

export function get-string:
    &(EventPayload, String) => String
    native '__UiEventPayloadGetString';

export function get-float:
    &(EventPayload, String) => NormalFloat
    native '__UiEventPayloadGetFloat';

export function get-integer:
    &(EventPayload, String) => Integer
    native '__UiEventPayloadGetInteger';

export function get-number:
    &(EventPayload, String) => Number
    native '__UiEventPayloadGetNumber';


